package com.acme.bankapp.util;

import java.util.LinkedList;
import java.util.List;

/**
 * Queue written via synchronized sections
 * @author Gregory Sobko
 */
public class BlockingQueue<T> implements ConcurrentQueue<T> {

    private final List<T> storage=new LinkedList<>();
    private int limit;
    private boolean isClosed = false;

    /**
     * @param limit max element in queue
     */
    public BlockingQueue(int limit) {
        this.limit = limit;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public T pop() throws InterruptedException {
        synchronized (storage){

            while(storage.isEmpty()){
                storage.wait();
            }
            storage.notifyAll();
            return storage.remove(0);

        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public T tryPop(){
        synchronized (storage){
            if(!storage.isEmpty()){
                storage.notifyAll();
                return storage.remove(0);
            }else{
                return null;
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void push(T element) throws InterruptedException {
        synchronized (storage){
            if(isClosed){
                throw new IllegalStateException("ConcurrentQueue is closed");
            }
            while(storage.size() >= limit){
                storage.wait();
            }
            storage.notifyAll();
            storage.add(element);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() {
        synchronized (storage){
            isClosed=true;
        }
    }
}
